package com.heima.datastructure.stack;

import java.util.Arrays;
import java.util.Iterator;

/**
 * 用数组实现栈
 *
 * @param <E>
 */
public class ArrayStack<E> implements Stack<E>, Iterable<E> {
    private E[] arr; // 数组
    private int top; // 栈顶指针，指向栈顶元素的后一个元素

    /**
     * 用构造器初始化
     *
     * @param capacity
     */
    @SuppressWarnings("all")
    public ArrayStack(int capacity) {
        arr = (E[]) new Object[capacity];
        top = 0;
    }

    /**
     * 向栈顶压入元素
     *
     * @param value 带压入值
     * @return 压入成功返回true
     */
    @Override
    public boolean push(E value) {
        if (isFull()) {
            return false;
        }
        arr[top++] = value;
        return true;
    }

    /**
     * 获取栈顶元素并删除，不存在返回null
     *
     * @return 栈顶元素的值
     */
    @Override
    public E pop() {
        if (isEmpty()) {
            return null;
        }
        E value = arr[--top];
        // 如果是基本类型，不用释放，例如int初始化为0还是四个字节，
        // 但是这里用了泛型，未来会被具体的对象替代，数组里面存的指针（对象的地址），
        // 指针指向这个对象，属于引用类型，该数组元素指向一个对象实例，
        // 当对象实例没有人指向它时才会被垃圾回收，所以这里要去掉指向该对象实例的指针
        arr[top] = null;
        return value;
    }

    /**
     * 获取栈顶元素的值但是不删除，不存在返回null
     *
     * @return 栈顶元素的值
     */
    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return arr[top - 1];
    }

    /**
     * 判断栈是否为空
     *
     * @return 栈为空返回true
     */
    @Override
    public boolean isEmpty() {
        return top == 0;
    }

    /**
     * 判断栈是否为满
     *
     * @return 为满返回true
     */
    @Override
    public boolean isFull() {
        return top == arr.length;
    }

    /**
     * 迭代器 这个迭代器是从栈底开始迭代
     *
     * @return 迭代器
     */
    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int index = 0;

            @Override
            public boolean hasNext() {
                return index != top;
            }

            @Override
            public E next() {
                return arr[index++];
            }
        };
    }

    /**
     * 扩容
     *
     * @param capacity 容量
     */
    @SuppressWarnings("all")
    public void expansion(int capacity) {
        if (capacity < arr.length) {
            throw new IllegalArgumentException("参数 [" + capacity + "] 不能比" + arr.length + "小");
        }
        E[] array = (E[]) new Object[capacity];
        System.arraycopy(arr, 0, array, 0, arr.length);
        arr = array;
    }
}
